package com.mobile.check.util;

import android.content.Context;
import android.os.Environment;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

import org.apache.poi.POIXMLDocument;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import cn.droidlover.xdroidmvp.kit.Kits;
import cn.droidlover.xdroidmvp.kit.NLog;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import com.mobile.check.db.EntityManager;
import com.mobile.check.beans.CheckFileInfo;
import com.mobile.check.beans.CheckItemInfo;

public class ScanUtil {
    private String checkPath = "检测系统/扫一扫/";
    private String picPath = "检测系统/扫一扫/图片/";
    private String checkbagPath = "检测系统/扫一扫/检测包/";
    Context context;

    String sRoot = Environment.getExternalStorageDirectory().getAbsolutePath();//获取跟目录

    public ScanUtil(Context context) {
        checkPath = sRoot + File.separator + checkPath;
        picPath = sRoot + File.separator + picPath;
        checkbagPath = sRoot + File.separator + checkbagPath;
    }

    private List<String> getZip2Files(String dirPath) {
        File zipDir = new File(dirPath);
        List<String> fileList = new ArrayList<>();
        File[] files = zipDir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                if (file.getPath().endsWith(".zip")) {
                    return true;
                }
                return false;
            }
        });
        for (File file : files) {
            fileList.add(file.getPath());
        }
        return fileList;
    }

    private File[] getZipFiles(String dirPath) {
        File zipDir = new File(dirPath);
        File[] files = zipDir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                if (pathname.getPath().endsWith(".zip")) {
                    return true;
                }
                return false;
            }
        });
        return files;
    }

    private File[] getXlsxFiles(String dirPath) {
        File zipDir = new File(dirPath);
        File[] files = zipDir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                if (pathname.getPath().endsWith(".xlsx")) {
                    return true;
                }
                return false;
            }
        });
        return files;
    }

    public void unZip(Observer<Boolean> subscribe) {
        Observable.create(new ObservableOnSubscribe<Boolean>() {
            @Override
            public void subscribe(ObservableEmitter<Boolean> e) throws Exception {

                List<String> fileList = getZip2Files(checkPath);
                List<CheckFileInfo> checkFileInfoList = EntityManager.getInstance().queryCheckFiles();

                if ((null == fileList || fileList.size() == 0) && checkFileInfoList.size() == 0) {
                    EntityManager.getInstance().delCheckFileInfo();
                    e.onError(new Throwable("暂无检测任务，请添加后"));
                } else {
                    for (CheckFileInfo checkFileInfo : checkFileInfoList) {
                        String xlsxPath = checkFileInfo.getXlsxPath();
                        String zipName = checkFileInfo.getZipName();
                        if (!Kits.File.isFileExist(xlsxPath)) {
                            EntityManager.getInstance().delCheckFile(checkFileInfo.getXlsxPath());
                            Kits.File.deleteFile(checkPath + File.separator + zipName);
                        } else {
                            checkZipFileModify(checkFileInfo);
                            fileList.remove(checkFileInfo.getFilePath());
                        }
                    }
                    for (String filePath : fileList) {
                        saveToDb(new File(filePath));
                    }
                    e.onNext(true);
                }

            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(subscribe);

    }


    private void checkZipFileModify(CheckFileInfo checkFileInfo) throws Exception {
        if (!Kits.File.isFileExist(checkFileInfo.getFilePath())) {
            return;
        }
        File zipfile = new File(checkFileInfo.getFilePath());
        long lastmodified = zipfile.lastModified();

        long dbLastmodified = checkFileInfo.getLastModified();
        if (dbLastmodified != lastmodified) {
            EntityManager.getInstance().delCheckFile(checkFileInfo.getXlsxPath());
            Kits.File.deleteFile(checkPath + File.separator + Kits.File.getFileNameWithoutExtension(zipfile.getPath()));
            saveToDb(new File(checkFileInfo.getFilePath()));
        }
//        saveToDb(new File(checkFileInfo.getFilePath()));
    }

    private void saveToDb(File zipFile) throws Exception {
        String driName = Kits.File.getFileNameWithoutExtension(zipFile.getName());
        String dirPath = checkPath + driName + File.separator;
        Kits.File.makeDirs(dirPath);
        Map<String, String> resultMap = ZipUtils.UnZipFolder(zipFile.getPath(), dirPath, dirPath);

        CheckFileInfo checkFileInfo = new CheckFileInfo();
        checkFileInfo.setFilePath(zipFile.getPath());
        checkFileInfo.setLastModified(zipFile.lastModified());
        checkFileInfo.setXlsxPath(resultMap.get("xlsxPath"));
        checkFileInfo.setPicDir(resultMap.get("picDir"));
        checkFileInfo.setXlsxName(Kits.File.getFileName(resultMap.get("xlsxPath")));
        checkFileInfo.setZipName(driName);
        long _ID = EntityManager.getInstance().saveCheckFIle(checkFileInfo);
        checkFileInfo.set_ID(_ID);
        dealCheckItems(checkFileInfo);

    }


    private void dealCheckItems(CheckFileInfo checkFileInfo) throws IOException {
        InputStream inputStream = null;
        try {
            NLog.d("ScanUtil", "xlsxPath=" + checkFileInfo.getXlsxPath());
            inputStream = new FileInputStream(checkFileInfo.getXlsxPath());
//            XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
            Workbook workbook = createworkbook(inputStream);
            Sheet sheet = workbook.getSheetAt(0);
//            XSSFSheet sheet = workbook.getSheetAt(0);

            List<CheckItemInfo> dataList = new ArrayList();
            int rowsCount = sheet.getPhysicalNumberOfRows();
            NLog.d("ScanUtil", "rowsCount=" + rowsCount);
//            Map<String, CheckItemGroupInfo> groupInfoMap = new HashMap<>();
            for (int i = 1; i < rowsCount; i++) {
                Row xssfRow = sheet.getRow(i);
                CheckItemInfo itemInfo = getTaskItemInfo(sheet, xssfRow);
                itemInfo.setPicPath(checkFileInfo.getPicDir() + itemInfo.getPicName());
                itemInfo.setBelongFileName(checkFileInfo.getXlsxName());
                dataList.add(itemInfo);
                NLog.d("ScanUtil", "itemInfo=" + itemInfo.toString());
            }
            NLog.d("ScanUtil", "itemSize=" + dataList.size());
            EntityManager.getInstance().saveCheckItemInfo(dataList);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != inputStream) {
                inputStream.close();
            }
        }

    }

    public static Workbook createworkbook(InputStream inp) throws IOException, InvalidFormatException {
        if (!inp.markSupported()) {
            inp = new PushbackInputStream(inp, 8);
        }
        if (POIFSFileSystem.hasPOIFSHeader(inp)) {
            return new HSSFWorkbook(inp);
        }
        if (POIXMLDocument.hasOOXMLHeader(inp)) {
            return new XSSFWorkbook(OPCPackage.open(inp));
        }
        throw new IllegalArgumentException("你的excel版本目前poi解析不了");
    }

    private CheckItemInfo getTaskItemInfo(Sheet sheet, Row row) {
        int rowNum = row.getRowNum();
        int firstCellNum = row.getFirstCellNum();
        int lastCellNum = row.getLastCellNum();

        NLog.d("getTaskItemInfo", "rowNum=" + rowNum + " firstCellNum=" + firstCellNum + " lastCellNum=" + lastCellNum);
        CheckItemInfo info = new CheckItemInfo();
        String itemName = "";
        JsonArray jsonArray = new JsonArray();
        String groupCode = "";
        String zujianPic = "";
        String leabel = "";
        for (int i = firstCellNum; i < lastCellNum; i++) {

            try {
                JsonObject jsonObject = new JsonObject();
                Cell cell = row.getCell(i);
                Cell xssfCell = sheet.getRow(0).getCell(i);
                if (null == xssfCell) {
                    continue;
                }
                String cellTitle = xssfCell.getStringCellValue();

                String value = convertCellValueToString(cell, cellTitle.contains("日期"));
                if ("组件图片".equals(cellTitle)) {
                    zujianPic = value;

                } else if ("群组编码".equals(cellTitle)) {
                    groupCode = value;
                } else if ("标签号".equals(cellTitle) || "标签".equals(cellTitle)) {
                    leabel = value;
                    info.setItemName(value);
                }
                jsonObject.addProperty("name", cellTitle);
                jsonObject.addProperty("value", value);
                jsonArray.add(jsonObject);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        NLog.d("scanUtil", "zujianPic=" + zujianPic + " groupCode=" + groupCode + " leabel=" + leabel);

        if (!TextUtils.isEmpty(zujianPic)) {
            info.setPicName(zujianPic);
            zujianPic = Kits.File.getFileNameWithoutExtension(zujianPic);
            info.setErCode(zujianPic);
        } else if (!TextUtils.isEmpty(groupCode)) {
            info.setPicName(zujianPic + ".jpeg");
            info.setErCode(groupCode);
        } else {
            String[] array = leabel.split("[.]");
            if (null != array && array.length > 1) {
                info.setErCode(array[0]);
                info.setPicName(array[0] + ".jpeg");

            }
        }


        String dataJson = new Gson().toJson(jsonArray);
        info.setDataJson(dataJson);
        return info;
    }

    private String convertCellValueToString(Cell cell, boolean isDate) {
        if (cell == null) {
            return "";
        }
        if (isDate) {
            try {
                return Kits.Date.getYmdhms2(cell.getDateCellValue().getTime());
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        String returnValue = "";
        switch (cell.getCellType()) {
            case 0: // 数字
                Double doubleValue = cell.getNumericCellValue();
                String valueStr = String.valueOf(doubleValue);

                DecimalFormat df;
                if (valueStr.contains(".0")) {
                    df = new DecimalFormat("0");
                } else {
                    df = new DecimalFormat("0.0");
                }
                NLog.d("valueStr", "valueStr=" + valueStr);
                returnValue = df.format(doubleValue);
                break;
            case 1: // 字符串
                returnValue = cell.getStringCellValue();
                break;
            case 4: // 布尔
                Boolean booleanValue = cell.getBooleanCellValue();
                returnValue = booleanValue.toString();
                break;
            case 3: // 空值
                break;
            case 2: // 公式
                returnValue = cell.getCellFormula();
                break;
            case 5: // 故障
                cell.getDateCellValue();
                break;
            default:
                break;
        }
        NLog.d("valueStr", "cellType = " + cell.getCellType() + " Value=" + returnValue);
        return returnValue;
    }
}
